﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Uber.Core;
using Uber.Storage;
using Uber.Net;
using Uber.HabboHotel;

namespace Uber
{
    class UberEnvironment
    {
        private static Logging Logging;
        private static ConfigurationData Configuration;
        private static DatabaseManager DatabaseManager;
        private static TcpConnectionManager ConnectionManager;
        private static Game Game;
        public static DateTime StartedEmulating;
        public static uint StartRoomId;
        public static Boolean OnlyStartRoom;
        public static uint uVipRoomId;

        public static DateTime ServerStarted;

        public static String PrettyVersion
        {
            get
            {
                return "uberEmulator - Breakz0nes Edit [R63, C#, MySQL]";
            }
        }

        public static void Initialize()
        {
            Console.Title = PrettyVersion;
            Console.WindowHeight = 20;
            Console.WindowWidth = 85;

            ServerStarted = DateTime.Now;

            Logging = new Logging();
            Logging.MinimumLogLevel = LogLevel.Debug;

            Console.BackgroundColor = ConsoleColor.DarkGray;
            Console.ForegroundColor = ConsoleColor.White;

            Console.WriteLine("        __          ____           __      __                                       ");
            Console.WriteLine("  __ __/ / ___ ____/ __/__ _ __ __/ /___,_/ /_____  ____    Professional Edition    ");
            Console.WriteLine(" / // / _ | -_) __/ _/ /  ' | // / // _  / __/ _  \\/ __/    www.breakz0ne.org/uber  ");
            Console.WriteLine(" \\_,_/_.__|__/_/ /___//_/_/_|_,_/_/ \\_,_/\\__/\\____/_/       Version 1.0.0.0         ");
            Console.WriteLine("                                                                                    ");

            Console.BackgroundColor = ConsoleColor.Black;

            Logging.ResetLogColor();

            Console.WriteLine("                                                                                    ");

            Logging.IsRunning = true;
            Logging.WriteLine("Initializing uberEmulator...");

            try
            {
                Configuration = new ConfigurationData("config.ini");

                if (UberEnvironment.GetConfig().data["db.password"].Length == 0)
                {
                    throw new Exception("For security reasons, your MySQL password cannot be left blank. Please change your password to start the server.");
                }

                if (UberEnvironment.GetConfig().data["db.password"] == "changeme")
                {
                    throw new Exception("Your MySQL password may not be 'changeme'.\nPlease change your password to start the server.");
                }

                if (int.Parse(UberEnvironment.GetConfig().data["db.pool.minsize"]) >= 25)
                {
                    throw new Exception("DB Pool Error\n\nYour MySQL minimum pool size must be lower than 25, you will flood MySQL.\n\nEven a value of 25 should only be used on very heavily loaded servers!");
                }

                DatabaseServer dbServer = new DatabaseServer(
                    UberEnvironment.GetConfig().data["db.hostname"],
                    uint.Parse(UberEnvironment.GetConfig().data["db.port"]),
                    UberEnvironment.GetConfig().data["db.username"],
                    UberEnvironment.GetConfig().data["db.password"]);

                Database db = new Database(
                    UberEnvironment.GetConfig().data["db.name"],
                    uint.Parse(UberEnvironment.GetConfig().data["db.pool.minsize"]),
                    uint.Parse(UberEnvironment.GetConfig().data["db.pool.maxsize"]));

                DatabaseManager = new DatabaseManager(dbServer, db);


                Game = new Game();
                
                ConnectionManager = new TcpConnectionManager(
                    UberEnvironment.GetConfig().data["game.tcp.bindip"],
                    int.Parse(UberEnvironment.GetConfig().data["game.tcp.port"]),int.Parse(UberEnvironment.GetConfig().data["game.tcp.conlimit"]));

                ConnectionManager.GetListener().Start();

                UberEnvironment.GetLogging().WriteLine("The environment has initialized successfully. Ready for connections.");
                Console.WriteLine("                                                            ");
                Console.Beep();

                StartedEmulating = DateTime.Now;
                StartRoomId = Convert.ToUInt32(UberEnvironment.GetConfig().data["addons.startroom.id"]);
                OnlyStartRoom = Convert.ToBoolean(UberEnvironment.GetConfig().data["addons.startroom.enabled"]);
                uVipRoomId = Convert.ToUInt32(UberEnvironment.GetConfig().data["uVip.publicroom.id"]);
            }

            catch (KeyNotFoundException)
            {
                Logging.WriteLine("Please check your configuration file - some values appear to be missing.", LogLevel.Error);
                Logging.WriteLine("Press any key to shut down ...", LogLevel.Error);

                Console.ReadKey(true);
                UberEnvironment.Destroy();

                return;
            }

            catch (InvalidOperationException e)
            {
                Logging.WriteLine("Failed to initialize: " + e.Message, LogLevel.Error);
                Logging.WriteLine("Press any key to shut down ...", LogLevel.Error);

                Console.ReadKey(true);
                UberEnvironment.Destroy();

                return;
            }
        }

        public static bool EnumToBool(string Enum)
        {
            return (Enum == "1");
        }

        public static string BoolToEnum(bool Bool)
        {
            if (Bool)
            {
                return "1";
            }

            return "0";
        }

        public static int GetRandomNumber(int Min, int Max)
        {
            RandomBase Quick = new Quick();
            return Quick.Next(Min, Max);
        }

        public static Double GetUnixTimestamp()
        {
            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            return ts.TotalSeconds;
        }

        public static string FilterInjectionChars(string Input)
        {
            return FilterInjectionChars(Input, false);
        }

        public static string FilterInjectionChars(string Input, bool AllowLinebreaks)
        {
            Input = Input.Replace(Convert.ToChar(1), ' ');
            Input = Input.Replace(Convert.ToChar(2), ' ');
            Input = Input.Replace(Convert.ToChar(3), ' ');
            Input = Input.Replace(Convert.ToChar(9), ' ');

            if (!AllowLinebreaks)
            {
                Input = Input.Replace(Convert.ToChar(13), ' ');
            }

            return Input;
        }

        public static bool IsValidAlphaNumeric(string inputStr)
        {
            if (string.IsNullOrEmpty(inputStr))
            {
                return false;
            }

            for (int i = 0; i < inputStr.Length; i++)
            {
                if (!(char.IsLetter(inputStr[i])) && (!(char.IsNumber(inputStr[i]))))
                {
                    return false;
                }
            }

            return true;
        }

        public static ConfigurationData GetConfig()
        {
            return Configuration;
        }

        public static Logging GetLogging()
        {
            return Logging;
        }

        public static DatabaseManager GetDatabase()
        {
            return DatabaseManager;
        }

        public static Encoding GetDefaultEncoding()
        {
            return Encoding.Default;
        }

        public static TcpConnectionManager GetConnectionManager()
        {
            return ConnectionManager;
        }

        public static Game GetGame()
        {
            return Game;
        }

        public static void Destroy()
        {
            UberEnvironment.GetLogging().WriteLine("Server is shutting down.");

            if (GetGame() != null)
            {
                GetGame().Destroy();
            }

            if (GetConnectionManager() != null)
            {
                UberEnvironment.GetLogging().WriteLine("Destroying connection manager.");
                GetConnectionManager().GetListener().Stop();
                GetConnectionManager().DestroyManager();
            }

            if (GetDatabase() != null)
            {
                UberEnvironment.GetLogging().WriteLine("Destroying database manager.");
                GetDatabase().StopClientMonitor();
                GetDatabase().DestroyClients();
                GetDatabase().DestroyDatabaseManager();
            }

            Logging.WriteLine("Uninitialized successfully. Closing.");

            Environment.Exit(0);
        }
    }
}
